/************************ (C) COPYLEFT 2018 Merafour *************************

* File Name          : engine3d.c
* Author             : Merafour
* Last Modified Date : 01/10/2019
* Description        :  3D engine.
********************************************************************************
* https://merafour.blog.163.com
* merafour@163.com
* https://github.com/merafour
******************************************************************************/
#include "Curve/Curve.h"	
#include <string.h>

// 3D engine
static void multiply(const int m, const int n, const int p, const float* const a, const float* const b, float* const c)// a[m][n] * b[n][p] = c[m][p]
{
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < p; j++) {
			c[i * p + j] = 0;
			for (int k = 0; k < n; k++) {
				c[i * p + j] += a[i * n + k] * b[k * p + j];
			}
		}
	}
}

void ArotateX(const uint16_t angle, const float* const point, float* const output)// rotate matrix for X
{
    /*static*/ float rotation[3][3];
    //memset((void*)rotation, 0, sizeof(rotation));
    rotation[0][0] = 1;
    rotation[1][1] = cos_table[angle];
    rotation[1][2] = 0 - sin_table[angle];
    rotation[2][1] = sin_table[angle];
    rotation[2][2] = cos_table[angle];
    multiply(3, 3, 1, (float*)rotation, point, output);
}
void ArotateY(const uint16_t angle, const float* const point, float* const output)// rotate matrix for Y
{
    /*static*/ float rotation[3][3];
    rotation[0][0] = cos_table[angle];
    rotation[0][2] = sin_table[angle];
    rotation[1][1] = 1;
    rotation[2][0] = 0 - sin_table[angle];
    rotation[2][2] = cos_table[angle];
    multiply(3, 3, 1, (float*)rotation, point, output);
}
void ArotateZ(const uint16_t angle, const float* const point, float* const output)// rotate matrix for Z
{
    /*static*/ float rotation[3][3];
    rotation[0][0] = cos_table[angle];
    rotation[0][1] = 0 - sin_table[angle];
    rotation[1][0] = sin_table[angle];
    rotation[1][1] = cos_table[angle];
    rotation[2][2] = 1;
    multiply(3, 3, 1, (float*)rotation, point, output);
}
void projectOnXY(const float* const point, float* const output, const float zFactor) //void projectOnXY(float* point, float* output, float zFactor = 1)
{
	static float projection[2][3];//project on X/Y face
	projection[0][0] = zFactor;//the raio of point.z and camera.z
	projection[1][1] = zFactor;//the raio of point.z and camera.z
    multiply(2, 3, 1, (float*)projection, point, output);
}

#if 0
void rotateX(float angle, float* point, float* output)// rotate matrix for X
{
    /*static*/ float rotation[3][3];
    //memset((void*)rotation, 0, sizeof(rotation));
	rotation[0][0] = 1;
	rotation[1][1] = cos(angle);
	rotation[1][2] = 0 - sin(angle);
	rotation[2][1] = sin(angle);
	rotation[2][2] = cos(angle);
	multiply(3, 3, 1, (float*)rotation, point, output);
}

void rotateY(float angle, float* point, float* output)// rotate matrix for Y
{
    /*static*/ float rotation[3][3];
	rotation[0][0] = cos(angle);
	rotation[0][2] = sin(angle);
	rotation[1][1] = 1;
	rotation[2][0] = 0 - sin(angle);
	rotation[2][2] = cos(angle);
    multiply(3, 3, 1, (float*)rotation, point, output);
}
void rotateZ(float angle, float* point, float* output)// rotate matrix for Z
{
    /*static*/ float rotation[3][3];
	rotation[0][0] = cos(angle);
	rotation[0][1] = 0 - sin(angle);
	rotation[1][0] = sin(angle);
	rotation[1][1] = cos(angle);
	rotation[2][2] = 1;	
    multiply(3, 3, 1, (float*)rotation, point, output);
}
#endif
